<script setup>
import { ref, onMounted} from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { getCases, deleteCase, createCase, updateCase, getProjects, executeCase } from '@/api/index.js'
import { Plus, Edit, Delete, View, VideoPlay } from '@element-plus/icons-vue'
import { useRouter } from 'vue-router'

// 添加防抖功能
const debounce = (fn, delay) => {
  let timeoutId
  return (...args) => {
    clearTimeout(timeoutId)
    timeoutId = setTimeout(() => fn.apply(null, args), delay)
  }
}

const router = useRouter()
const cases = ref([])
const loading = ref(false)
const createDialogVisible = ref(false)
const editDialogVisible = ref(false)
const createLoading = ref(false)
const editLoading = ref(false)
const currentEditId = ref(null)
const executeLoading = ref(false)
const projects = ref([])
const pagination = ref({
  currentPage: 1,
  pageSize: 10,
  total: 0
})

const searchForm = ref({
  title: '',
  method: '',
  priority: ''
})

const caseForm = ref({
  title: '',
  description: '',
  url: '',
  method: 'GET',
  headers: '{}',
  params: '{}',
  body: '{}',
  expected_result: '',
  priority: 'MEDIUM',
  project: ''
})

const editForm = ref({
  title: '',
  description: '',
  url: '',
  method: 'GET',
  headers: '{}',
  params: '{}',
  body: '{}',
  expected_result: '',
  priority: 'MEDIUM',
  project: ''
})

const formRules = {
  title: [
    { required: true, message: '请输入用例标题', trigger: 'blur' },
    { min: 2, max: 200, message: '用例标题长度在 2 到 200 个字符', trigger: 'blur' }
  ],
  description: [
    { required: true, message: '请输入用例描述', trigger: 'blur' }
  ],
  url: [
    { required: true, message: '请输入请求地址', trigger: 'blur' },
    { 
      validator: (rule, value, callback) => {
        if (!value) {
          callback(new Error('请输入请求地址'))
          return
        }
        
        // 检查是否以斜杠开头（必须）
        if (!value.startsWith('/')) {
          callback(new Error('请求地址必须以斜杠(/)开头，如：/api/user'))
          return
        }
        
        // 检查是否包含有效字符（只允许路径字符）
        const pathPattern = /^\/[a-zA-Z0-9\-_\/\{\}]*$/
        if (!pathPattern.test(value)) {
          callback(new Error('请求地址格式不正确，只能包含字母、数字、斜杠、连字符和下划线'))
          return
        }
        
        callback()
      }, 
      trigger: 'blur' 
    }
  ],
  method: [
    { required: true, message: '请选择请求方法', trigger: 'change' }
  ],
  expected_result: [
    { required: true, message: '请输入期望结果', trigger: 'blur' }
  ],
  priority: [
    { required: true, message: '请选择优先级', trigger: 'change' }
  ],
  project: [
    { required: true, message: '请选择所属项目', trigger: 'change' }
  ]
}

const caseFormRef = ref()
const editFormRef = ref()

const fetchCases = async () => {
  loading.value = true
  try {
    const params = {
      page: pagination.value.currentPage,
      size: pagination.value.pageSize,
      title: searchForm.value.title,
      method: searchForm.value.method,
      priority: searchForm.value.priority
    }
    const res = await getCases(params)
    if (res.status === 200) {
      cases.value = res.data.results || []
      pagination.value.total = res.data.count || 0
    }
  } catch (error) {
    ElMessage.error('获取用例列表失败')
  } finally {
    loading.value = false
  }
}

const debouncedSearch = debounce(() => {
  pagination.value.currentPage = 1
  fetchCases()
}, 500)

const handleSearch = () => {
  pagination.value.currentPage = 1
  fetchCases()
}

const handleInputSearch = () => {
  debouncedSearch()
}


const handleDelete = async (row) => {
  try {
    await ElMessageBox.confirm('确定要删除此用例吗？', '删除确认', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning',
    })
    
    const res = await deleteCase(row.id)
    
    // 检查后端返回的 status 字段（现在是 200）
    if (res && res.status === 200) {
      ElMessage.success(res.msg || '删除成功')
      await fetchCases()
    } else {
      ElMessage.error(`删除失败: ${res?.msg || '未知错误'}`)
    }
  } catch (error) {
    if (error !== 'cancel') {
      console.error('删除用例出错:', error)
      // 如果是网络错误或其他错误
      if (error.response) {
        // 服务器响应了错误状态码
        ElMessage.error(`删除失败: ${error.response.data?.msg || error.response.statusText}`)
      } else if (error.request) {
        // 请求已发出但没有收到响应
        ElMessage.error('删除失败: 网络错误')
      } else {
        // 其他错误
        ElMessage.error(`删除失败: ${error.message}`)
      }
    }
  }
}

const formatDate = (dateString) => {
  if (!dateString) return '-'
  try {
    return new Date(dateString).toLocaleString('zh-CN')
  } catch (error) {
    return '-'
  }
}

const getPriorityTag = (priority) => {
  const priorityMap = {
    'HIGH': { type: 'danger', text: '高' },
    'MEDIUM': { type: 'warning', text: '中' },
    'LOW': { type: 'success', text: '低' }
  }
  return priorityMap[priority] || { type: '', text: priority }
}

const getMethodTag = (method) => {
  const methodMap = {
    'GET': { type: 'success', text: 'GET' },
    'POST': { type: 'primary', text: 'POST' },
    'PUT': { type: 'warning', text: 'PUT' },
    'DELETE': { type: 'danger', text: 'DELETE' }
  }
  return methodMap[method] || { type: 'info', text: method }
}

const methodOptions = [
  { label: 'GET', value: 'GET' },
  { label: 'POST', value: 'POST' },
  { label: 'PUT', value: 'PUT' },
  { label: 'DELETE', value: 'DELETE' }
]

const priorityOptions = [
  { label: '高', value: 'HIGH' },
  { label: '中', value: 'MEDIUM' },
  { label: '低', value: 'LOW' }
]

const fetchProjects = async () => {
  try {
    const res = await getProjects({ page: 1, size: 1000 })
    if (res.status === 200) {
      projects.value = res.data.results || []
    }
  } catch (error) {
    ElMessage.error('获取项目列表失败')
  }
}

const showCreateDialog = () => {
  createDialogVisible.value = true
  caseForm.value = {
    title: '',
    description: '',
    url: '',
    method: 'GET',
    headers: '{}',
    params: '{}',
    body: '{}',
    expected_result: '',
    priority: 'MEDIUM',
    project: ''
  }
  fetchProjects()
}

const validateJSON = (value, field) => {
  try {
    JSON.parse(value)
    return true
  } catch (error) {
    ElMessage.error(`${field} 必须是有效的JSON格式`)
    return false
  }
}

const handleCreateSubmit = async () => {
  if (!caseFormRef.value) return
  
  await caseFormRef.value.validate(async (valid) => {
    if (valid) {
      if (!validateJSON(caseForm.value.headers, '请求头') ||
          !validateJSON(caseForm.value.params, '请求参数') ||
          !validateJSON(caseForm.value.body, '请求体')) {
        return
      }
      
      createLoading.value = true
      try {
        const formData = {
          ...caseForm.value,
          name: caseForm.value.title, // 确保发送 name 字段
          headers: JSON.parse(caseForm.value.headers),
          params: JSON.parse(caseForm.value.params),
          body: JSON.parse(caseForm.value.body)
        }
        
        const res = await createCase(formData)
        if (res && res.status === 201) {
          ElMessage.success(res.msg || '用例创建成功')
          createDialogVisible.value = false
          fetchCases()
        } else {
          ElMessage.error(`用例创建失败: ${res?.msg || '未知错误'}`)
        }
      } catch (error) {
        console.error('用例创建错误:', error)
        ElMessage.error(`用例创建失败: ${error.response?.data?.msg || error.message}`)
      } finally {
        createLoading.value = false
      }
    }
  })
}

const handleCreateCancel = () => {
  createDialogVisible.value = false
  caseForm.value = {
    title: '',
    description: '',
    url: '',
    method: 'GET',
    headers: '{}',
    params: '{}',
    body: '{}',
    expected_result: '',
    priority: 'MEDIUM',
    project: ''
  }
}

const handleEdit = (row) => {
  currentEditId.value = row.id
  editForm.value = {
    title: row.title,
    description: row.description || '',
    url: row.url || '',
    method: row.method || 'GET',
    headers: JSON.stringify(row.headers || {}, null, 2),
    params: JSON.stringify(row.params || {}, null, 2),
    body: JSON.stringify(row.body || {}, null, 2),
    expected_result: row.expected_result || '',
    priority: row.priority || 'MEDIUM',
    project: row.project
  }
  editDialogVisible.value = true
  fetchProjects()
}

const handleEditSubmit = async () => {
  if (!editFormRef.value) return
  
  await editFormRef.value.validate(async (valid) => {
    if (valid) {
      if (!validateJSON(editForm.value.headers, '请求头') ||
          !validateJSON(editForm.value.params, '请求参数') ||
          !validateJSON(editForm.value.body, '请求体')) {
        return
      }
      
      editLoading.value = true
      try {
        const formData = {
          ...editForm.value,
          name: editForm.value.title, // 确保发送 name 字段
          headers: JSON.parse(editForm.value.headers),
          params: JSON.parse(editForm.value.params),
          body: JSON.parse(editForm.value.body)
        }
        
        const res = await updateCase(currentEditId.value, formData)
        if (res && res.status === 200) {
          ElMessage.success(res.msg || '用例更新成功')
          editDialogVisible.value = false
          fetchCases()
        } else {
          ElMessage.error(`用例更新失败: ${res?.msg || '未知错误'}`)
        }
      } catch (error) {
        console.error('用例更新错误:', error)
        ElMessage.error(`用例更新失败: ${error.response?.data?.msg || error.message}`)
      } finally {
        editLoading.value = false
      }
    }
  })
}

const handleEditCancel = () => {
  editDialogVisible.value = false
  editForm.value = {
    title: '',
    description: '',
    url: '',
    method: 'GET',
    headers: '{}',
    params: '{}',
    body: '{}',
    expected_result: '',
    priority: 'MEDIUM',
    project: ''
  }
  currentEditId.value = null
}

const handleExecute = async (row) => {
  try {
    await ElMessageBox.confirm(
      `确定要执行测试用例 "${row.title}" 吗？`,
      '执行确认',
      {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'info',
      }
    )
    
    executeLoading.value = true
    ElMessage.info('正在执行测试用例，请稍候...')
    
    // 调用执行API
    const res = await executeCase(row.id, {
      case_id: row.id,
      execution_time: new Date().toISOString()
    })
    
    executeLoading.value = false
    
    if (res.status === 200) {
      ElMessage.success('测试用例执行完成')
      await fetchCases() // 执行后刷新状态
      // 可以在这里打开执行结果对话框或跳转到结果页面
      console.log('执行结果:', res.data)
    } else {
      ElMessage.error('执行测试用例失败')
    }
    
  } catch (error) {
    if (error !== 'cancel') {
      executeLoading.value = false
      ElMessage.error('执行测试用例失败')
    }
  }
}

onMounted(() => {
  fetchCases()
})
</script>

<template>
  <div class="case-list">
    <el-card>
      <template #header>
        <div class="card-header">
          <span>测试用例管理</span>
          <el-button type="primary" :icon="Plus" @click="showCreateDialog">
            新建用例
          </el-button>
        </div>
      </template>

      <!-- 搜索区域 -->
      <div class="search-area">
        <el-form :model="searchForm" inline>
          <el-form-item label="用例标题">
            <el-input v-model="searchForm.title" placeholder="请输入用例标题" clearable @input="handleInputSearch" />
          </el-form-item>
          <el-form-item label="请求方法">
            <el-select 
              v-model="searchForm.method" 
              placeholder="请选择请求方法" 
              clearable
              @change="handleSearch"
            >
              <el-option
                v-for="option in methodOptions"
                :key="option.value"
                :label="option.label"
                :value="option.value"
              />
            </el-select>
          </el-form-item>
          <el-form-item label="优先级">
            <el-select 
              v-model="searchForm.priority" 
              placeholder="请选择优先级" 
              clearable
              @change="handleSearch"
            >
              <el-option
                v-for="option in priorityOptions"
                :key="option.value"
                :label="option.label"
                :value="option.value"
              />
            </el-select>
          </el-form-item>
        </el-form>
      </div>

      <!-- 表格区域 -->
      <el-table :data="cases" v-loading="loading" stripe>
        <el-table-column prop="title" label="用例标题" />
        <el-table-column prop="url" label="请求地址" show-overflow-tooltip />
        <el-table-column prop="method" label="请求方法" width="100">
          <template #default="scope">
            <el-tag :type="getMethodTag(scope.row.method).type">
              {{ getMethodTag(scope.row.method).text }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column label="执行状态" width="100">
          <template #default="scope">
            <el-tag v-if="scope.row.latest_execution" :type="scope.row.latest_execution.status === 'success' ? 'success' : (scope.row.latest_execution.status === 'failed' ? 'danger' : (scope.row.latest_execution.status === 'running' ? 'warning' : 'info'))">
              {{ scope.row.latest_execution.status === 'success' ? '成功' : (scope.row.latest_execution.status === 'failed' ? '失败' : (scope.row.latest_execution.status === 'running' ? '执行中' : '未执行')) }}
            </el-tag>
            <span v-else>-</span>
          </template>
        </el-table-column>
        <el-table-column label="执行结果" min-width="120">
          <template #default="scope">
            <span v-if="scope.row.latest_execution && scope.row.latest_execution.result">{{ scope.row.latest_execution.result }}</span>
            <span v-else>-</span>
            <el-link v-if="scope.row.latest_execution && scope.row.latest_execution.report_url" :href="scope.row.latest_execution.report_url" target="_blank" type="primary" style="margin-left:8px;">报告</el-link>
          </template>
        </el-table-column>
        <el-table-column prop="priority" label="优先级" width="100">
          <template #default="scope">
            <el-tag :type="getPriorityTag(scope.row.priority).type">
              {{ getPriorityTag(scope.row.priority).text }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="project_name" label="所属项目" />
        <el-table-column label="创建时间" width="180">
          <template #default="scope">
            {{ formatDate(scope.row.created_at || scope.row.created_time) }}
          </template>
        </el-table-column>
        <el-table-column label="操作" width="200" fixed="right">
          <template #default="scope">
            <el-button size="small" type="success" :icon="VideoPlay" @click="handleExecute(scope.row)" :loading="executeLoading">
              执行
            </el-button>
            <el-button size="small" type="primary" :icon="Edit" @click="handleEdit(scope.row)">
              编辑
            </el-button>
            <el-button size="small" type="danger" :icon="Delete" @click="handleDelete(scope.row)">
              删除
            </el-button>
          </template>
        </el-table-column>
      </el-table>

      <!-- 分页区域 -->
      <div class="pagination-area">
        <el-pagination
          v-model:current-page="pagination.currentPage"
          v-model:page-size="pagination.pageSize"
          :page-sizes="[10, 20, 50, 100]"
          :total="pagination.total"
          layout="total, sizes, prev, pager, next, jumper"
          @size-change="fetchCases"
          @current-change="fetchCases"
        />
      </div>
    </el-card>

    <!-- 创建测试用例对话框 -->
    <el-dialog 
      v-model="createDialogVisible" 
      title="创建测试用例" 
      width="700px"
      :close-on-click-modal="false"
    >
      <el-form
        ref="caseFormRef"
        :model="caseForm"
        :rules="formRules"
        label-width="100px"
        size="default"
      >
        <el-form-item label="用例标题" prop="title">
          <el-input
            v-model="caseForm.title"
            placeholder="请输入用例标题"
            maxlength="200"
            show-word-limit
          />
        </el-form-item>

        <el-form-item label="用例描述" prop="description">
          <el-input
            v-model="caseForm.description"
            type="textarea"
            placeholder="请输入用例描述"
            :rows="3"
            maxlength="1000"
            show-word-limit
          />
        </el-form-item>

        <el-form-item label="所属项目" prop="project">
          <el-select v-model="caseForm.project" placeholder="请选择所属项目" style="width: 100%">
            <el-option
              v-for="project in projects"
              :key="project.id"
              :label="project.name"
              :value="project.id"
            />
          </el-select>
        </el-form-item>

        <el-form-item label="请求地址" prop="url">
          <el-input
            v-model="caseForm.url"
            placeholder="请输入请求地址，如：/api/user（必须以/开头）"
          />
          <div class="help-text">
            <el-text size="small" type="info">
              请求地址格式示例：/api/user，注意必须以斜杠(/)开头
            </el-text>
          </div>
        </el-form-item>

        <el-form-item label="请求方法" prop="method">
          <el-radio-group v-model="caseForm.method">
            <el-radio label="GET">GET</el-radio>
            <el-radio label="POST">POST</el-radio>
            <el-radio label="PUT">PUT</el-radio>
            <el-radio label="DELETE">DELETE</el-radio>
          </el-radio-group>
        </el-form-item>

        <el-form-item label="优先级" prop="priority">
          <el-radio-group v-model="caseForm.priority">
            <el-radio label="HIGH">高</el-radio>
            <el-radio label="MEDIUM">中</el-radio>
            <el-radio label="LOW">低</el-radio>
          </el-radio-group>
        </el-form-item>

        <el-form-item label="请求头">
          <el-input
            v-model="caseForm.headers"
            type="textarea"
            placeholder='请输入请求头，JSON格式，如：{"Content-Type": "application/json"}'
            :rows="2"
          />
        </el-form-item>

        <el-form-item label="请求参数">
          <el-input
            v-model="caseForm.params"
            type="textarea"
            placeholder='请输入请求参数，JSON格式，如：{"page": 1, "size": 10}'
            :rows="2"
          />
        </el-form-item>

        <el-form-item label="请求体">
          <el-input
            v-model="caseForm.body"
            type="textarea"
            placeholder='请输入请求体，JSON格式，如：{"name": "test", "email": "test@example.com"}'
            :rows="3"
          />
        </el-form-item>

        <el-form-item label="期望结果" prop="expected_result">
          <el-input
            v-model="caseForm.expected_result"
            type="textarea"
            placeholder="请输入期望的返回结果或验证规则"
            :rows="2"
            maxlength="1000"
            show-word-limit
          />
        </el-form-item>
      </el-form>

      <template #footer>
        <span class="dialog-footer">
          <el-button @click="handleCreateCancel">取消</el-button>
          <el-button type="primary" @click="handleCreateSubmit" :loading="createLoading">
            创建
          </el-button>
        </span>
      </template>
    </el-dialog>

    <!-- 编辑测试用例对话框 -->
    <el-dialog 
      v-model="editDialogVisible" 
      title="编辑测试用例" 
      width="700px"
      :close-on-click-modal="false"
    >
      <el-form
        ref="editFormRef"
        :model="editForm"
        :rules="formRules"
        label-width="100px"
        size="default"
      >
        <el-form-item label="用例标题" prop="title">
          <el-input
            v-model="editForm.title"
            placeholder="请输入用例标题"
            maxlength="200"
            show-word-limit
          />
        </el-form-item>

        <el-form-item label="用例描述" prop="description">
          <el-input
            v-model="editForm.description"
            type="textarea"
            placeholder="请输入用例的详细描述"
            :rows="2"
            maxlength="500"
            show-word-limit
          />
        </el-form-item>

        <el-form-item label="所属项目" prop="project">
          <el-select v-model="editForm.project" placeholder="请选择所属项目" style="width: 100%">
            <el-option
              v-for="project in projects"
              :key="project.id"
              :label="project.name"
              :value="project.id"
            />
          </el-select>
        </el-form-item>

        <el-form-item label="请求地址" prop="url">
          <el-input
            v-model="editForm.url"
            placeholder="请输入请求地址，如：/api/user（必须以/开头）"
          />
          <div class="help-text">
            <el-text size="small" type="info">
              请求地址格式示例：/api/user，注意必须以斜杠(/)开头
            </el-text>
          </div>
        </el-form-item>

        <el-form-item label="请求方法" prop="method">
          <el-radio-group v-model="editForm.method">
            <el-radio label="GET">GET</el-radio>
            <el-radio label="POST">POST</el-radio>
            <el-radio label="PUT">PUT</el-radio>
            <el-radio label="DELETE">DELETE</el-radio>
          </el-radio-group>
        </el-form-item>

        <el-form-item label="优先级" prop="priority">
          <el-radio-group v-model="editForm.priority">
            <el-radio label="HIGH">高</el-radio>
            <el-radio label="MEDIUM">中</el-radio>
            <el-radio label="LOW">低</el-radio>
          </el-radio-group>
        </el-form-item>

        <el-form-item label="请求头">
          <el-input
            v-model="editForm.headers"
            type="textarea"
            placeholder='请输入请求头，JSON格式，如：{"Content-Type": "application/json"}'
            :rows="2"
          />
        </el-form-item>

        <el-form-item label="请求参数">
          <el-input
            v-model="editForm.params"
            type="textarea"
            placeholder='请输入请求参数，JSON格式，如：{"page": 1, "size": 10}'
            :rows="2"
          />
        </el-form-item>

        <el-form-item label="请求体">
          <el-input
            v-model="editForm.body"
            type="textarea"
            placeholder='请输入请求体，JSON格式，如：{"name": "test", "email": "test@example.com"}'
            :rows="3"
          />
        </el-form-item>

        <el-form-item label="期望结果" prop="expected_result">
          <el-input
            v-model="editForm.expected_result"
            type="textarea"
            placeholder="请输入期望的返回结果或验证规则"
            :rows="2"
            maxlength="1000"
            show-word-limit
          />
        </el-form-item>
      </el-form>

      <template #footer>
        <span class="dialog-footer">
          <el-button @click="handleEditCancel">取消</el-button>
          <el-button type="primary" @click="handleEditSubmit" :loading="editLoading">
            更新
          </el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<style scoped lang="less">
.case-list {
  .card-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
  }

  .search-area {
    margin-bottom: 20px;
    padding: 20px;
    background-color: #f5f7fa;
    border-radius: 4px;
  }

  .pagination-area {
    margin-top: 20px;
    display: flex;
    justify-content: flex-end;
  }

  .help-text {
    margin-top: 8px;
    
    .el-text {
      line-height: 1.4;
    }
  }
}
</style>